package cn.bonoon.kernel.support.services.handler;

import java.util.List;

import javax.persistence.EntityManager;

import cn.bonoon.kernel.events.OperateEvent;
import cn.bonoon.kernel.support.entities.EntityMovable;
import cn.bonoon.kernel.support.entities.Persistable;

public abstract class AbstractMovableHandler implements OperateHandler {
	
	private final String targetNode;
	private final String updateOrdinal;
	private final String movedownNode;
	private final String moveupNode;
	
	protected AbstractMovableHandler(String entityName, String targetQl, String increaseQl, String decreaseQl){
		this.targetNode = "select x.id, x.ordinal from " + entityName + " x where x.ordinal" + targetQl;
		this.movedownNode = "update " + entityName + " set ordinal=ordinal+1 where ordinal<? and ordinal" + increaseQl;
		this.moveupNode = "update " + entityName + " set ordinal=ordinal-1 where ordinal>? and ordinal" + decreaseQl;
		this.updateOrdinal = "update " + entityName + " set ordinal=%d where id=%d";
	}
	
	@Override
	public Object handler(EntityManager entityManager, OperateEvent event, Persistable entity) {
		EntityMovable source = (EntityMovable)entity;
		int sourceOrder = source.getOrdinal();
		List<?> ois = entityManager.createQuery(targetNode).setParameter(1, sourceOrder).setMaxResults(1).getResultList();
		if(ois.size() == 1){
			Object[] oi = (Object[])ois.get(0);
			entityManager.createQuery(String.format(updateOrdinal, sourceOrder, oi[0])).executeUpdate();
			entityManager.clear();
			source.setOrdinal(((Number)oi[1]).intValue());
			entityManager.merge(source);
		}
		return "移动实体:" + source.getId();
	}
	
	/**
	 * 当sourceOrder > targetOrder时应该更新的序号
	 * @param targetOrder
	 * @return
	 */
	protected int getOrdinalSourceeGreate(int targetOrder){return targetOrder;}
	/**
	 * 当sourceOrder < targetOrder时应该更新的序号
	 * @param targetOrder
	 * @return
	 */
	protected int getOrdinalTargetGreate(int targetOrder){return targetOrder;}
	
	@Override
	public MultiOperateHandlerExecuter handler(final EntityManager entityManager, final OperateEvent event) {
		return new MultiOperateHandlerExecuter(){
			EntityMovable source;
			EntityMovable target;
			@Override
			public MultiOperateHandlerExecuter addParameter(Persistable entity) {
				if(null == source){
					source = (EntityMovable)entity;
				}else if(null == target){
					target = (EntityMovable)entity;
				}else{
					throw new RuntimeException("参数不正确！");
				}
				return this;
			}

			@Override
			public void execute() {
				int sourceOrder = source.getOrdinal();//被移动的节点ID
				int targetOrder = target.getOrdinal();
				if(sourceOrder > targetOrder){//被移动的节点ID > 移动到的节点ID
					entityManager.createQuery(movedownNode)
						.setParameter(1, sourceOrder)
						.setParameter(2, targetOrder)
						.executeUpdate();
					entityManager.clear();
					source.setOrdinal(getOrdinalSourceeGreate(targetOrder));
					entityManager.merge(source);
				}else if(sourceOrder < targetOrder){
					entityManager.createQuery(moveupNode)
						.setParameter(1, sourceOrder)
						.setParameter(2, targetOrder)
						.executeUpdate();
					entityManager.clear();
					source.setOrdinal(getOrdinalTargetGreate(targetOrder));
					entityManager.merge(source);
				}
			}
			
		};
	}
}
